Skip to content
This repository was archived by the owner on Dec 9, 2025. It is now read-only.

Add OpenAI Whisper transcription with in-app settings - #6

Merged
unforced merged 2 commits into
mainfrom
feature/whisper-transcription
Oct 5, 2025
Merged

Add OpenAI Whisper transcription with in-app settings#6
unforced merged 2 commits into
mainfrom
feature/whisper-transcription

Conversation

@unforced

@unforced unforced commented Oct 4, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR adds AI-powered transcription to the Parachute voice recorder app using OpenAI's Whisper API.

Features Added

  • OpenAI Whisper Integration: Transcribe recordings with industry-leading accuracy
  • Settings Screen: User-friendly interface for API key management
  • Secure Storage: API keys stored in SharedPreferences (no hardcoded keys)
  • One-Click Transcription: Transcribe button on post-recording screen
  • Smart UX: Helpful dialogs and navigation when API key is missing

Technical Changes

  • Created WhisperService for OpenAI API communication
  • Changed recording format from AAC/ADTS to M4A (Whisper compatible)
  • Added url_launcher and http packages
  • Implemented API key management in StorageService
  • Disabled real-time transcription due to Android microphone conflict

Bug Fixes

  • Fixed microphone access conflict between flutter_sound and speech_to_text
  • Removed unused real-time transcription code

Screenshots

Settings screen includes:

  • API key status indicator
  • Secure input field with show/hide
  • Link to OpenAI dashboard
  • Pricing information
  • Delete functionality

Testing

  • ✅ Record audio and transcribe
  • ✅ Settings navigation
  • ✅ API key save/delete
  • ✅ Error handling for missing/invalid keys
  • ✅ M4A playback

Cost

Transcription costs $0.006 per minute (~$0.36 per hour)

Setup Required

Users need to:

  1. Get OpenAI API key from platform.openai.com/api-keys
  2. Add it in Settings
  3. Tap Transcribe on any recording

Features:
- Integrated OpenAI Whisper API for audio transcription
- Added Settings screen for API key configuration
- Secure API key storage using SharedPreferences
- One-click transcription from post-recording screen
- Helpful user guidance and error handling

Technical changes:
- Created WhisperService for OpenAI API integration
- Changed recording format from AAC/ADTS to M4A for Whisper compatibility
- Added settings UI with API key management and validation
- Implemented secure storage for API keys (no hardcoded keys)
- Added url_launcher and http dependencies
- Updated PostRecordingScreen with transcribe button
- Disabled real-time transcription (microphone conflict on Android)

UI improvements:
- Settings icon in app bar for easy access
- API key status indicators (configured/not configured)
- Password-style input with show/hide toggle
- Direct link to OpenAI dashboard
- Pricing information display
- Smart navigation to Settings when API key missing

Bug fixes:
- Fixed microphone access conflict between flutter_sound and speech_to_text
- Removed unused transcription service from recording screen
- Updated audio codec for better compatibility
@claude

claude Bot commented Oct 4, 2025

Copy link
Copy Markdown
Contributor

Claude finished @unforced's task —— View job


📝 Pull Request Code Review

I've completed a comprehensive review of this PR that adds OpenAI Whisper transcription functionality. Here's my analysis:


Strengths

Code Quality & Architecture

  • Well-structured services: WhisperService follows clean separation of concerns with proper error handling
  • Consistent patterns: Follows existing app patterns using singleton services and Flutter state management
  • Good error handling: Comprehensive exception handling with user-friendly error messages
  • Security-conscious: API keys stored in SharedPreferences (not hardcoded), with validation

User Experience

  • Smart navigation: Automatically redirects to settings when API key is missing
  • Clear feedback: Loading states, progress indicators, and informative snackbars
  • Intuitive UI: Clean settings screen with status indicators and helpful instructions

Technical Implementation

  • Format compatibility: Smart switch from AAC to M4A for Whisper API compatibility
  • Cost transparency: Clear pricing information displayed to users
  • Proper resource management: Controllers disposed correctly, mounted checks prevent setState errors

⚠️ Areas for Improvement

Security Concerns

lib/services/whisper_service.dart:73,83

print('Sending audio to Whisper API for transcription...');
print('Transcription successful (${text.length} characters)');
  • Issue: Debug prints may expose sensitive API interactions in production logs
  • Fix: Remove or wrap in debug-only conditionals

Error Handling Edge Cases

lib/services/whisper_service.dart:87-88

final errorBody = jsonDecode(response.body);
final errorMessage = errorBody['error']?['message'] ?? 'Unknown error';
  • Issue: Could throw if response body isn't valid JSON
  • Fix: Add try-catch around jsonDecode

Code Quality Issues

lib/screens/post_recording_screen.dart:279

color: Colors.grey.withValues(alpha: 0.7),
  • Issue: withValues() is deprecated in newer Flutter versions
  • Fix: Use withOpacity(0.7) instead

lib/services/storage_service.dart:175-177

Future<String?> getOpenAIApiKey() async {
  final prefs = await SharedPreferences.getInstance();
  return prefs.getString(_openaiApiKeyKey);
}
  • Issue: No error handling for SharedPreferences operations
  • Fix: Add try-catch blocks

Performance Considerations

lib/screens/settings_screen.dart:36-42

final apiKey = await _storageService.getOpenAIApiKey();
if (apiKey != null && apiKey.isNotEmpty) {
  _apiKeyController.text = apiKey;
  _hasApiKey = true;
}
  • Issue: Loads full API key into text field (security & performance)
  • Fix: Only show masked version or status

🔍 Missing Elements

Test Coverage

  • No unit tests for WhisperService
  • No widget tests for SettingsScreen
  • No integration tests for transcription flow

Documentation

  • Missing API documentation for WhisperService methods
  • No error code documentation for different failure scenarios

Validation

  • API key format validation is basic (only checks sk- prefix)
  • No validation of API key with actual OpenAI API call

🛡️ Security Assessment

Good Practices

  • ✅ API keys stored locally, not in code
  • ✅ Basic format validation prevents obviously invalid keys
  • ✅ Proper HTTPS usage for API calls

Recommendations

  • Consider encrypting API keys in SharedPreferences
  • Add rate limiting for transcription requests
  • Implement API key validation endpoint call

🎯 Recommendations

High Priority

  1. Remove debug prints that could expose sensitive data
  2. Fix deprecated withValues() usage
  3. Add error handling for JSON parsing and SharedPreferences

Medium Priority

  1. Add basic unit tests for WhisperService
  2. Implement API key validation with OpenAI
  3. Consider encrypting stored API keys

Low Priority

  1. Add integration tests for full transcription flow
  2. Optimize settings screen to not load full API key

📊 Overall Assessment

This is a solid implementation that adds valuable functionality while maintaining good code quality and user experience. The architecture is sound, error handling is comprehensive, and the security approach is reasonable for a mobile app.

Recommended Action: ✅ Approve with minor fixes

The identified issues are mostly minor and don't block the core functionality. The security concerns are addressable through the suggested improvements.


Todo List:

  • Read and analyze key changed files
  • Review code quality and best practices
  • Check for potential bugs and issues
  • Assess performance considerations
  • Identify security concerns
  • Evaluate test coverage
  • Provide comprehensive feedback

@claude

claude Bot commented Oct 4, 2025

Copy link
Copy Markdown
Contributor

Claude finished @unforced's task —— View job


📝 Pull Request Code Review

I've completed a comprehensive review of this PR that adds OpenAI Whisper transcription functionality. Here's my analysis:


Strengths

Code Quality & Architecture

  • Well-structured services: WhisperService follows clean separation of concerns with proper error handling
  • Consistent patterns: Follows existing app patterns using singleton services and Flutter state management
  • Good error handling: Comprehensive exception handling with user-friendly error messages
  • Security-conscious: API keys stored in SharedPreferences (not hardcoded), with validation

User Experience

  • Smart navigation: Automatically redirects to settings when API key is missing
  • Clear feedback: Loading states, progress indicators, and informative snackbars
  • Intuitive UI: Clean settings screen with status indicators and helpful instructions

Technical Implementation

  • Format compatibility: Smart switch from AAC to M4A for Whisper API compatibility
  • Cost transparency: Clear pricing information displayed to users
  • Proper resource management: Controllers disposed correctly, mounted checks prevent setState errors

⚠️ Areas for Improvement

Code Quality Issues

Multiple files using deprecated API:

color: Colors.grey.withValues(alpha: 0.7),
  • Issue: withValues() is deprecated in newer Flutter versions
  • Fix: Use withOpacity(0.7) instead
  • Files affected: post_recording_screen.dart, home_screen.dart, recording_tile.dart, recording_visualizer.dart

Error Handling Edge Cases

lib/services/whisper_service.dart:84-87

final errorBody = jsonDecode(response.body);
final errorMessage = errorBody['error']?['message'] ?? 'Unknown error';
  • Issue: Could throw if response body isn't valid JSON
  • Fix: Add try-catch around jsonDecode

lib/services/storage_service.dart:182-184

Future<String?> getOpenAIApiKey() async {
  final prefs = await SharedPreferences.getInstance();
  return prefs.getString(_openaiApiKeyKey);
}
  • Issue: No error handling for SharedPreferences operations
  • Fix: Add try-catch blocks

Performance Considerations

lib/screens/settings_screen.dart:36-42

final apiKey = await _storageService.getOpenAIApiKey();
if (apiKey != null && apiKey.isNotEmpty) {
  _apiKeyController.text = apiKey;
  _hasApiKey = true;
}
  • Issue: Loads full API key into text field (security & performance)
  • Fix: Only show masked version or status

🔍 Missing Elements

Test Coverage

  • No unit tests for WhisperService
  • No widget tests for SettingsScreen
  • No integration tests for transcription flow

Documentation

  • Missing API documentation for WhisperService methods
  • No error code documentation for different failure scenarios

Validation

  • API key format validation is basic (only checks sk- prefix)
  • No validation of API key with actual OpenAI API call

🛡️ Security Assessment

Good Practices

  • ✅ API keys stored locally, not in code
  • ✅ Basic format validation prevents obviously invalid keys
  • ✅ Proper HTTPS usage for API calls

Recommendations

  • Consider encrypting API keys in SharedPreferences
  • Add rate limiting for transcription requests
  • Implement API key validation endpoint call

🎯 Recommendations

High Priority

  1. Fix deprecated withValues() usage across multiple files
  2. Add error handling for JSON parsing and SharedPreferences
  3. Remove or conditionally wrap debug print statements

Medium Priority

  1. Add basic unit tests for WhisperService
  2. Implement API key validation with OpenAI
  3. Consider encrypting stored API keys

Low Priority

  1. Add integration tests for full transcription flow
  2. Optimize settings screen to not load full API key

📊 Overall Assessment

This is a solid implementation that adds valuable functionality while maintaining good code quality and user experience. The architecture is sound, error handling is comprehensive, and the security approach is reasonable for a mobile app.

Recommended Action: ✅ Approve with minor fixes

The identified issues are mostly minor and don't block the core functionality. The security concerns are addressable through the suggested improvements.


Todo List:

  • Read and analyze key changed files
  • Review code quality and best practices
  • Check for potential bugs and issues
  • Assess performance considerations
  • Identify security concerns
  • Evaluate test coverage
  • Provide comprehensive feedback

@unforced
unforced merged commit 92079d0 into main Oct 5, 2025
1 check passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant